home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / hdf / unix / hdf3_2r2.lha / HDF3.2r2 / util / he_main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-28  |  29.4 KB  |  1,391 lines

  1. /***************************************************************************
  2. *
  3. *
  4. *                         NCSA HDF version 3.2r2
  5. *                            October 30, 1992
  6. *
  7. * NCSA HDF Version 3.2 source code and documentation are in the public
  8. * domain.  Specifically, we give to the public domain all rights for future
  9. * licensing of the source code, all resale rights, and all publishing rights.
  10. *
  11. * We ask, but do not require, that the following message be included in all
  12. * derived works:
  13. *
  14. * Portions developed at the National Center for Supercomputing Applications at
  15. * the University of Illinois at Urbana-Champaign, in collaboration with the
  16. * Information Technology Institute of Singapore.
  17. *
  18. * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
  19. * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
  20. * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
  21. *
  22. ****************************************************************************
  23. */
  24.  
  25. #ifdef RCSID
  26. static char RcsId[] = "@(#)$Revision: 1.7 $";
  27. #endif
  28. /*
  29. $Header: /hdf/hdf/v3.2r2/util/RCS/he_main.c,v 1.7 1992/10/13 20:30:23 koziol beta koziol $
  30.  
  31. $Log: he_main.c,v $
  32.  * Revision 1.7  1992/10/13  20:30:23  koziol
  33.  * Updates for v3.2r2 release
  34.  * .,
  35.  *
  36.  * Revision 1.1  1992/09/18  14:56:22  koziol
  37.  * Initial revision
  38.  *
  39.  * Revision 1.9  1992/09/17  21:19:36  chouck
  40.  * Fixed backup file name so VMS would be happy.  No backups for PCs
  41.  *
  42.  * Revision 1.8  1992/09/15  19:34:24  chouck
  43.  * Fixed minor typo
  44.  *
  45.  * Revision 1.7  1992/09/11  18:32:51  chouck
  46.  * Assorted MAC mungings
  47.  *
  48.  * Revision 1.6  1992/08/25  20:49:45  chouck
  49.  * Fixed backup name generation so its easier to open non-local files
  50.  *
  51.  * Revision 1.5  1992/08/24  22:00:44  sxu
  52.  * Use vfork() and delete() for VMS
  53.  *
  54.  * Revision 1.4  1992/07/31  21:10:24  chouck
  55.  * Use in-house print routines rather than fork() a call to od
  56.  *
  57.  * Revision 1.3  1992/07/15  21:48:48  sxu
  58.  * No change.
  59.  *
  60.  * Revision 1.2  1992/07/14  17:50:30  mlivin
  61.  * updated help with no pixrect, name of 'hdfed' not 'he'
  62.  *
  63.  * Revision 1.1  1992/07/06  22:54:16  mlivin
  64.  * Initial revision
  65.  *
  66. */
  67. /******************************************************************************
  68.  * he - HDF editor
  69.  *
  70.  * This program has a long history, starting with its creation as a tool to
  71.  * help HDF developers work at a low-level on HDF files.  It has evolved into
  72.  * user-level program, though it is still designed for small editing tasks on
  73.  * HDF files.
  74.  *
  75.  * he allows sophisticated HDF users to manipulate the elements in an HDF file.
  76.  * These manipulations include selecting groups and showing information about
  77.  * them, dumping them to the output, writing them to new files, deleting them,
  78.  * inserting them, replacing, say, the palette of an r8 group, and editing the
  79.  * text labels and descriptions of any element.
  80.  *
  81.  * he will NOT allow the user to *arbitrarily* modify binary data in the file
  82.  * or any element, though it allows modification of tag and reference numbers
  83.  * within strict constraints.  The user should not attempt to alter individual
  84.  * bytes.  It is acceptable, however, to replace an element with another of
  85.  * the same type.
  86.  *
  87.  * he can be used both interactively or in "batch" mode.  Here is a sample
  88.  * batch program:
  89.  *
  90.  *      #!/bin/csh -f
  91.  *      set file=$1
  92.  *      shift
  93.  *      he -batch $file -nobackup << EOF
  94.  *      info -all -group $*
  95.  *      close
  96.  *      quit
  97.  *      EOF
  98.  *
  99.  * This makes use of C-shell variable substitution to pass a filename to he,
  100.  * invokes he, and then lists out on separate lines the commands to give once
  101.  * he is running.  The $* trailing the info command is also C-shell variable
  102.  * substitution.
  103.  *
  104.  * List of commands:       annotate   dump    if      open    putr8    unalias
  105.  *                         close      getr8   info    prev    revert   wait
  106.  *                         delete     help    next    put     select   write
  107.  *                         display 
  108.  *
  109.  * Predicates are of the form TAG = 3 IMAGE_SIZE < 1000  LABEL = "abc"
  110.  * Type <command> -help for usage of <command>.  DO NOT type the command
  111.  * without arguments and expect help.  Some commands delete objects and do not
  112.  * need any arguments.  If you are learning to use he, try it on an expendable
  113.  * file.
  114.  *****************************************************************************/
  115. /* ------ he.c ------- main() main HDF interfacing routines */
  116. #include "he.h"
  117. #include "herr.h"
  118.  
  119. /* the return status of last command executed */
  120. int he_status = HE_OK;
  121.  
  122. /* is this on the console or remote terminals?
  123.    this should eventually be detected automatically */
  124. int he_remote = YES;
  125.  
  126. /* is this batch mode or interactive? */
  127. extern int he_batch;
  128.  
  129. #ifdef PROTOTYPE
  130. int main(int argc, char *argv[])
  131. #else
  132. int main(argc, argv)
  133.     int argc;
  134.     char *argv[];
  135. #endif
  136. {
  137.     int backup = YES;        /* Backup files when opening? */
  138.     register int i;
  139.     char *fileName = NULL;
  140.     
  141.     for (i = 1; i < argc; i++) {
  142.     if (argv[i][0] == '-') {
  143.         switch (findOpt(argv[i] + 1)) {
  144.             case HE_HELP:
  145.         printf("he [<file>] [-nobackup] [-batch]\n");
  146.         help();
  147.         quit(0);
  148.                 break;
  149.         case HE_BATCH:
  150.         he_batch = YES;
  151.         break;
  152.         case HE_REMOTE:
  153.         he_remote = YES;
  154.         break;
  155.         case HE_NOBACKUP:
  156.         backup = NO;
  157.         break;
  158.         case HE_BACKUP:
  159.         backup = YES;
  160.         break;
  161.         case HE_NOTFOUND:
  162.         unkOpt(argv[i]);
  163.         quit(1);    /* does not return */
  164.         break;
  165.         case HE_AMBIG:
  166.         ambigOpt(argv[i]);
  167.         quit(1);
  168.         break;
  169.         default:
  170.         irrOpt(argv[i]);
  171.         quit(1);    /* does not return */
  172.         break;
  173.         }
  174.     }
  175.     else
  176.     {
  177.         /* Must be a filename */
  178.         if (!fileName)
  179.         fileName = argv[i];
  180.         else
  181.         fprintf(stderr, "Single file only. %s not open.\n", argv[i]);
  182.     }
  183.     }
  184.  
  185.     /* if there is a file name given in the command line, open it */
  186.  
  187. #ifdef PC
  188.     backup = FALSE;
  189. #endif /* PC */
  190.  
  191.     if (fileName) he_status = openFile(fileName, backup);
  192.  
  193.     /* read, execute loop */
  194.     cmdLoop();
  195.  
  196.     if (fileOpen()) close(YES);    /* close with keep */
  197.     quit(0);
  198.     return 0;
  199. }
  200.  
  201. /* cmdLoop -- read commands and execute them */
  202. #ifdef PROTOTYPE
  203. void cmdLoop(void)
  204. #else
  205. void cmdLoop()
  206. #endif
  207. {
  208.     HE_CMD *cmd;
  209.  
  210.     for (cmd = getCmd(); cmd; cmd = getCmd())
  211.     {
  212.     if (cmd->func)
  213.         he_status = (*cmd->func) (cmd);
  214.     else
  215.     {
  216.         fprintf(stderr, "Unknown command: %s.\n", cmd->argv[0]);
  217.         he_status = HE_FAIL;
  218.     }
  219.     deleteCmd(cmd);
  220.     }
  221. }
  222.  
  223. int he_currDesc;
  224. int he_numDesc;
  225. int he_numGrp;
  226. int he_backup;
  227. char *he_file;
  228. DFdesc he_desc[HE_DESC_SZ];
  229. HE_GROUP he_grp[HE_DESC_SZ];
  230.     
  231. #ifdef PROTOTYPE
  232. int32 getElement(int desc, char **pdata)
  233. #else
  234. int32 getElement(desc, pdata)
  235.     int desc;
  236.     char **pdata;
  237. #endif
  238. {
  239.     int32 length;
  240.     int32 fid;
  241.  
  242.     length = he_desc[desc].length;
  243.  
  244.     /* alloc memory to read the element in */
  245.     *pdata = (char *) malloc(length);
  246.     if (*pdata == NULL) return FAIL;
  247.  
  248.     /* read in the element and check for error */
  249.     if ((fid = Hopen(he_file, DFACC_READ, 0)) == (int32)NULL) {
  250.       HEprint(stderr, 0);
  251.       return FAIL;
  252.     }
  253.     if (Hgetelement(fid, he_desc[desc].tag, he_desc[desc].ref, (unsigned char *) (*pdata)) < 0) {
  254.       free(*pdata);
  255.       fprintf(stderr, "Cannot read element.\n");
  256.       return FAIL;
  257.     }
  258.     Hclose(fid);
  259.     return length;
  260. }
  261.  
  262. /* The function is not called.
  263.  
  264. #ifdef PROTOTYPE
  265. int od(char *format, char *file)
  266. #else
  267. int od(format, file)
  268.     char *format;
  269.     char *file;
  270. #endif
  271. {
  272.      fork a child and let the child run od. Use vfork for VMS.
  273.  
  274.     if (fork() == 0)
  275.  
  276.     {
  277.        this is the child 
  278.  
  279.     if (execl("/bin/od", "od", format, file, 0) == -1)
  280.         fprintf(stderr, "Error while executing od.\n");
  281.  
  282.        return control to the parent 
  283.     exit(0);
  284.     }
  285.  
  286.       the parent waits for the child to die 
  287.  
  288.     wait(0);
  289.  
  290.       this is a bug because it always returns OK, will expand this as
  291.        soon as the status return mechanism from wait is understood 
  292.     return HE_OK;
  293.  
  294. }
  295. */
  296.  
  297. /* the tmp directory, currently set for unix */
  298. #define TDIR "/tmp/"
  299.  
  300. #ifdef PROTOTYPE
  301. int getTmpName(char **pname)
  302. #else
  303. int getTmpName(pname)
  304.     char **pname;
  305. #endif
  306. {
  307.     int length;
  308.     static int count = 0;
  309.     char s[32];
  310.  
  311.     (void) sprintf(s, "%she%d.%d", TDIR, getpid(), count);
  312.     count++;
  313.  
  314.     length = strlen(s);
  315.     if (length <= 0) return FAIL;
  316.  
  317.     *pname = (char *) malloc(length+1);
  318.     strcpy(*pname, s);
  319.  
  320.     return length;
  321. }
  322.  
  323. #ifdef PROTOTYPE
  324. int writeToFile(char *file, char *data, int32 length)
  325. #else
  326. int writeToFile(file, data, length)
  327.     char *file;
  328.     char *data;
  329.     int32 length;
  330. #endif
  331. {
  332.     FILE *fd;
  333.     int written;
  334.  
  335.     fd = fopen(file, "w");
  336.     if (fd == NULL) return FAIL;
  337.  
  338.     written = fwrite(data, sizeof(char), length, fd);
  339.     if (written != length)
  340.     {
  341.     fprintf(stderr,"Error in write.\n");
  342.     return FAIL;
  343.     }
  344.     fclose(fd);
  345.  
  346.     return HE_OK;
  347. }
  348.  
  349. #ifdef PROTOTYPE
  350. int removeFile(char *file)
  351. #else
  352. int removeFile(file)
  353.     char *file;
  354. #endif
  355. {
  356. #ifndef VMS
  357.     return unlink(file);
  358. #else
  359.     return remove((const char *)file);
  360. #endif
  361. }
  362.  
  363. /* is a file currently opened */
  364. #ifdef PROTOTYPE
  365. int fileOpen(void)
  366. #else
  367. int fileOpen()
  368. #endif
  369. {
  370.     return (he_file != NULL);
  371. }
  372.  
  373. #ifdef PROTOTYPE
  374. char *backupName(char *file)
  375. #else
  376. char *backupName(file)
  377.     char *file;
  378. #endif
  379. {
  380.     return catStr(file, "$hdfed$");
  381. }
  382.  
  383. #ifdef PROTOTYPE
  384. int backupFile(char *file)
  385. #else
  386. int backupFile(file)
  387.     char *file;
  388. #endif
  389. {
  390.     char *back;            /* backup file name */
  391.  
  392.     back = backupName(file);
  393.     return copyFile(file, back);
  394. }
  395.  
  396. #ifdef PROTOTYPE
  397. int copyFile(char *from, char *to)
  398. #else
  399. int copyFile(from, to)
  400.     char *from, *to;
  401. #endif
  402. {
  403.     int read;
  404.     char buf[HE_BUF_SZ];    /* copying buffer */
  405.     FILE *fp;
  406.     FILE *bfp;
  407.  
  408.     /* open the hdf file for backing up */
  409.     if ((fp = fopen(from, "r")) == NULL)
  410.     {
  411.     fprintf(stderr,"Unable to open file: <%s>\n",from);
  412.     return FAIL;
  413.     }
  414.     if ((bfp = fopen(to, "w")) == NULL)
  415.     {
  416.     fclose(fp);
  417.     fprintf(stderr,"Unable to open backup file.\n");
  418.     return FAIL;
  419.     }
  420.     /* copy the contents from hdf file to backup file */
  421.     while ((read = fread(buf, 1, HE_BUF_SZ, fp)) > 0)
  422.     fwrite(buf, 1, read, bfp);
  423.  
  424.     fclose(fp);
  425.     fclose(bfp);
  426.  
  427.     return HE_OK;
  428. }
  429.  
  430. #ifdef PROTOTYPE
  431. int updateDesc(void)
  432. #else
  433. int updateDesc()
  434. #endif
  435. {
  436.   uint32 fid;
  437.   int32 aid, status;
  438.   register int i, j;
  439.   
  440.   if(!(fid = Hopen(he_file, DFACC_READ, 0))) {
  441.     printf("failed opening\n");
  442.     HEprint(stdout, 0);
  443.     return FAIL;
  444.   }    
  445.   
  446.   aid = Hstartread(fid, DFTAG_WILDCARD, DFREF_WILDCARD);
  447.   if(aid == FAIL) {
  448.     HEprint(stderr, 0);
  449.     return FAIL;
  450.   }
  451.   
  452.   status = SUCCEED;
  453.   for(i = 0; (i < HE_DESC_SZ) && (status != FAIL); i++) {
  454.     Hinquire(aid, NULL, &he_desc[i].tag, &he_desc[i].ref, &he_desc[i].length,
  455.              &he_desc[i].offset, NULL, (int16 *) NULL, (int16 *) NULL);
  456.     status = Hnextread(aid, DFTAG_WILDCARD, DFREF_WILDCARD, DF_CURRENT);
  457.   }
  458.   he_numDesc = i;    
  459.   
  460.   /* get informations about the groups */
  461.   he_numGrp = 0;
  462.   for (i = 0; i < he_numDesc; i++) {
  463.     if (isGrp(he_desc[i].tag)) {
  464.       he_grp[he_numGrp].desc = i;
  465.       he_grp[he_numGrp].size = he_desc[i].length / sizeof(tag_ref);
  466.       he_grp[he_numGrp].ddList = (tag_ref_ptr) malloc(he_desc[i].length);
  467.       
  468.       if (!he_grp[he_numGrp].ddList) {
  469.         fprintf(stderr, "Out of memory. Closing file.\n");
  470.         closeFile(1);    /* keep the backup */
  471.         return FAIL;
  472.       }
  473.       if (DFdiread(fid, he_desc[i].tag, he_desc[i].ref) < 0) {
  474.         HEprint(stderr, 0);
  475.         return FAIL;
  476.       }
  477.       for (j = 0; j < he_grp[he_numGrp].size; j++)
  478.         DFdiget(&he_grp[he_numGrp].ddList[j].tag, 
  479.                 &he_grp[he_numGrp].ddList[j].ref);
  480.       
  481.       he_numGrp++;
  482.     }
  483.   }
  484.   Hclose(fid);
  485.   return SUCCEED;
  486. }
  487.  
  488.  
  489. #ifdef PROTOTYPE
  490. int initFile(char *file)
  491. #else
  492. int initFile(file)
  493.     char *file;
  494. #endif
  495. {
  496.     if (he_file) free(he_file);
  497.     he_file = copyStr(file);
  498.  
  499.     if (updateDesc() < 0)
  500.     return FAIL;
  501.  
  502.     /* if there are groups in this file, go to the first group tag */
  503.     /* otherwise, just go to the first element */
  504.     if (he_numGrp > 0)
  505.     he_currDesc = he_grp[0].desc;
  506.     else
  507.     he_currDesc = 0;
  508.  
  509.     return resetPred();
  510. }
  511.  
  512. #ifdef PROTOTYPE
  513. int closeFile(int keep)
  514. #else
  515. int closeFile(keep)
  516.     int keep;
  517. #endif
  518. {
  519.     register int i;
  520.     char *back;
  521.  
  522.     if (!fileOpen())
  523.     {
  524.     fprintf(stderr, "No open file to close.\n");
  525.     return FAIL;
  526.     }
  527.     /* free some dynamic storages */
  528.     if (he_backup && !keep)
  529.     {
  530.     back = backupName(he_file);
  531.     (void) removeFile(back);
  532.     free(back);
  533.     }
  534.     free(he_file);
  535.     he_file = NULL;
  536.     for (i = 0; i < he_numGrp; i++)
  537.     free(he_grp[i].ddList);
  538.  
  539.     return HE_OK;
  540. }
  541.  
  542. #ifdef PROTOTYPE
  543. int getR8(int xdim, int ydim, char *image, char *pal, int compress)
  544. #else
  545. int getR8(xdim, ydim, image, pal, compress)
  546.     int xdim, ydim;
  547.     char *image;
  548.     char *pal;
  549.     int compress;
  550. #endif
  551. {
  552.     FILE *fp;
  553.     int32 length;
  554.     char *buf;
  555.  
  556.     if (!fileOpen())
  557.     {
  558.     noFile();
  559.     return FAIL;
  560.     }
  561.     if (pal) 
  562.     if (setPal(pal) < 0)
  563.         /* Error already signalled by setPal */
  564.         return FAIL;
  565.  
  566.     length = xdim * ydim;
  567.     buf = (char *) malloc(length);
  568.  
  569.     if ((fp = fopen(image, "r")) == NULL)
  570.     {
  571.     fprintf(stderr,"Error opening image file: %s.\n", image);
  572.     return FAIL;
  573.     }
  574.     if (fread(buf, xdim, ydim, fp) < ydim)
  575.     {
  576.     fprintf(stderr,"Error reading image file: %s.\n", image);
  577.     return FAIL;
  578.     }
  579.     fclose(fp);
  580.  
  581.     if (DFR8addimage(he_file, buf, xdim, ydim, compress) < 0)
  582.     {
  583.     HEprint(stderr, 0);
  584.     return FAIL;
  585.     }
  586.     free(buf);
  587.  
  588.     if (updateDesc() < 0)
  589.     return FAIL;
  590.  
  591.     return HE_OK;
  592. }
  593.  
  594. #ifdef PROTOTYPE
  595. int setPal(char *pal)
  596. #else
  597. int setPal(pal)
  598.     char *pal;
  599. #endif
  600. {
  601.     FILE *fp;
  602.     char reds[HE_COLOR_SZ], greens[HE_COLOR_SZ], blues[HE_COLOR_SZ];
  603.     char palette[HE_PALETTE_SZ];
  604.     register char *p;
  605.     register int i;
  606.  
  607.     if ((fp = fopen(pal, "r")) == NULL)
  608.     {
  609.     fprintf(stderr,"Error opening palette file: %s.\n", pal);
  610.     return FAIL;
  611.     }
  612.     if (fread(reds, 1, HE_COLOR_SZ, fp) < HE_COLOR_SZ ||
  613.     fread(greens, 1, HE_COLOR_SZ, fp) < HE_COLOR_SZ ||
  614.     fread(blues, 1, HE_COLOR_SZ, fp) < HE_COLOR_SZ)
  615.     {
  616.     fprintf(stderr, "Error reading palette file: %s.\n", pal);
  617.     return FAIL;
  618.     }
  619.  
  620.     /* convert sun palette to hdf palette */
  621.     p = palette;
  622.     for (i = 0; i < HE_COLOR_SZ; i++)
  623.     {
  624.     *p++ = reds[i];
  625.     *p++ = greens[i];
  626.     *p++ = blues[i];
  627.     }
  628.  
  629.     if (DFR8setpalette((uint8*) palette) < 0)
  630.     {
  631.     fputs("Error setting palette.\n",stderr);
  632.     return FAIL;
  633.     }
  634.  
  635.     return HE_OK;
  636. }
  637.  
  638. #ifdef PROTOTYPE
  639. int findDesc(tag_ref_ptr dd)
  640. #else
  641. int findDesc(dd)
  642.     tag_ref_ptr dd;
  643. #endif
  644. {
  645.     register int i;
  646.  
  647.     for (i = 0; i < he_numDesc; i++)
  648.     if ((he_desc[i].tag == dd->tag) && (he_desc[i].ref == dd->ref))
  649.         return i;
  650.  
  651.     return FAIL;
  652. }
  653.  
  654. #ifdef PROTOTYPE
  655. int desc2Grp(int desc)
  656. #else
  657. int desc2Grp(desc)
  658.     int desc;
  659. #endif
  660. {
  661.     register int i;
  662.  
  663.     for (i = 0; i < he_numGrp; i++)
  664.     if (he_grp[i].desc == desc) return i;
  665.  
  666.     NOT_REACHED();
  667.     return FAIL;
  668. }
  669.  
  670. #ifdef PROTOTYPE
  671. int hasReference(int desc)
  672. #else
  673. int hasReference(desc)
  674.     int desc;
  675. #endif
  676. {
  677.     register int i, j;
  678.  
  679.     for (i = 0; i < he_numGrp; i++)
  680.     for (j = 0; j < he_grp[i].size ; j++)
  681.         if (he_grp[i].ddList[j].tag == he_desc[desc].tag &&
  682.         he_grp[i].ddList[j].ref == he_desc[desc].ref)
  683.         return YES;
  684.     return NO;
  685. }
  686.  
  687. #ifdef PROTOTYPE
  688. int deleteDesc(int desc)
  689. #else
  690. int deleteDesc(desc)
  691.     int desc;
  692. #endif
  693. {
  694.     int32 fid;
  695.  
  696.     if ((fid = Hopen(he_file, DFACC_WRITE, 0)) == (int32)NULL) {
  697.       HEprint(stderr, 0);
  698.       return FAIL;
  699.     }
  700.  
  701.     if (Hdeldd(fid, he_desc[desc].tag, he_desc[desc].ref) == FAIL)
  702.     {
  703.     HEprint(stderr, 0);
  704.     return FAIL;
  705.     }
  706.     return Hclose(fid);
  707. }
  708.  
  709. #ifdef PROTOTYPE
  710. int getCurrRig(int32 *pXdim, int32 *pYdim, char **pPalette, char **pRaster)
  711. #else
  712. int getCurrRig(pXdim, pYdim, pPalette, pRaster)
  713.     int32 *pXdim, *pYdim;
  714.     char **pPalette;
  715.     char **pRaster;
  716. #endif
  717. {
  718.     int ispal;
  719.  
  720.     goTo(he_currDesc);
  721.  
  722.     if (DFR8getdims(he_file, pXdim, pYdim, &ispal)<0)
  723.     {
  724.     fprintf(stderr, "Error getting image group.\n");
  725.     HEprint(stderr, 0);
  726.     return FAIL;
  727.     }
  728.     if (ispal)
  729.     *pPalette = (char *) malloc(HE_PALETTE_SZ);
  730.     else
  731.     *pPalette = (char *) NULL;
  732.     *pRaster = (char *) malloc((*pXdim) * (*pYdim));
  733.  
  734.     if (DFR8getimage(he_file, (unsigned char *) *pRaster, *pXdim, *pYdim, 
  735.                      (unsigned char *) *pPalette) == FAIL) 
  736.     {
  737.     fprintf(stderr, "Error getting image group.\n");
  738.     HEprint(stderr, 0);
  739.     return FAIL;
  740.     }
  741.  
  742.     return HE_OK;
  743. }
  744.  
  745. #ifdef PROTOTYPE
  746. int putWithTempl(char *template, int n1, int n2, int n3, char *data, int length, int verbose)
  747. #else
  748. int putWithTempl(template, n1, n2, n3, data, length, verbose)
  749.     char *template;
  750.     int n1, n2, n3;
  751.     char *data;
  752.     int length;
  753.     int verbose;
  754. #endif
  755. {
  756.     char *file;
  757.     int ret;
  758.  
  759.     convertTemplate(template, n1, n2, n3, &file);
  760.     if (verbose)
  761.     printf("Writing to file: %s\n", file);
  762.     ret = writeToFile(file, data, length);
  763.     free(file);
  764.  
  765.     return ret;
  766. }
  767.  
  768. #ifdef PROTOTYPE
  769. int revert(void)
  770. #else
  771. int revert()
  772. #endif
  773. {
  774.     char *back;
  775.  
  776.     back = backupName(he_file);
  777.     if (copyFile(back, he_file) < 0)
  778.     return FAIL;
  779.     return initFile(he_file);
  780. }
  781.  
  782. #ifdef PROTOTYPE
  783. int writeElt(char *file, uint16 ref, int elt)
  784. #else
  785. int writeElt(file, ref, elt)
  786.     char *file;
  787.     uint16 ref;
  788.     int elt;
  789. #endif
  790. {
  791.     int ret;
  792.     char *data;
  793.     int32 eltLength;
  794.     char *p;
  795.     uint16 rank;
  796.     register int i;
  797.     uint16 ntTag;
  798.     uint16 ntRef;
  799.     tag_ref_ptr ntDesc;
  800.     int nt;
  801.  
  802.     eltLength = getElement(elt, &data);
  803.     if (eltLength <= 0) {
  804.       fprintf(stderr,"Cannot get element: tag %d ref %d.\n",
  805.               he_desc[elt].tag, he_desc[elt].ref);
  806.       return FAIL;
  807.     }
  808.     /* special case */
  809.  
  810.     if (he_desc[elt].tag == DFTAG_SDD) {
  811.  
  812.       /* lots of hack here */
  813.       /* assume that the number types are of the same ref as this elt */
  814.       p = data;
  815.       
  816.       /* get the rank */
  817.       /* NOTE: UINT16READ and UINT16WRITE advances p */
  818.       UINT16DECODE(p, rank);
  819.       /* move to the NT of the data */
  820.       p += (rank * 4);
  821.       UINT16DECODE(p, ntTag);
  822.       UINT16DECODE(p, ntRef);
  823.       
  824.       /* set up to write the number type element */
  825.       ntDesc = (tag_ref_ptr) malloc(sizeof(tag_ref));
  826.       ntDesc->tag = ntTag;
  827.       ntDesc->ref = ntRef;
  828.       nt = findDesc(ntDesc);
  829.       free(ntDesc);
  830.       writeElt(file, ref, nt);
  831.       
  832.       p -= 2;
  833.       UINT16ENCODE(p, ref);
  834.       /* do the NT of scales */
  835.       for (i = 0; i < rank; i++) {
  836.         p += 2;
  837.         UINT16ENCODE(p, ref);
  838.       }
  839.     }
  840.  
  841.     ret = putElement(file, he_desc[elt].tag, ref, data, eltLength);
  842.     free(data);
  843.     return ret;
  844. }
  845.  
  846. #ifdef PROTOTYPE
  847. int putElement(char *file, uint16 tag, uint16 ref, char *data, int32 len)
  848. #else
  849. int putElement(file, tag, ref, data, len)
  850.     char *file;
  851.     uint16 tag;
  852.     uint16 ref;
  853.     char *data;
  854.     int32 len;
  855. #endif
  856. {
  857.     int ret;
  858.     int32 fid;
  859.  
  860.     if ((fid = Hopen(file, DFACC_READ | DFACC_WRITE, 0)) == (uint32)NULL)
  861.     /* a little tricky here */
  862.     if (HEvalue(0) != DFE_FNF || (fid = Hopen(file, DFACC_ALL, 0)) == (uint32)NULL)
  863.     {
  864.         HEprint(stderr, 0);
  865.         return FAIL;
  866.     }
  867.     if ((ret = Hputelement(fid, tag, ref, (unsigned char *) data, len)) < 0)
  868.     {
  869.     HEprint(stderr, 0);
  870.     return ret;
  871.     }
  872.     return Hclose(fid);
  873. }
  874.  
  875. #ifdef PROTOTYPE
  876. int writeGrp(char *file)
  877. #else
  878. int writeGrp(file)
  879.     char *file;
  880. #endif
  881. {
  882.     register int i;
  883.     uint16 ref;
  884.     int grp;
  885.     int elt;
  886.     int ret;
  887.     int32 fid;
  888.  
  889.     getNewRef(file, &ref);
  890.  
  891.     grp = currGrpNo();
  892.     DFdisetup(he_grp[grp].size);
  893.     for (i = 0; i < he_grp[grp].size; i++) {
  894.       elt = findDesc(he_grp[grp].ddList + i);
  895.       if (elt >= 0)
  896.         writeElt(file, ref, elt);
  897.       /* update the group dd list */
  898.       DFdiput(he_grp[grp].ddList[i].tag, ref);
  899.     }
  900.     /* do the group now */
  901.  
  902.     if ((fid = Hopen(file, DFACC_READ | DFACC_WRITE, 0)) == (uint32)NULL)
  903.     {
  904.     HEprint(stderr, 0);
  905.     return FAIL;
  906.     }
  907.     if ((ret = DFdiwrite(fid, currTag(), ref)) < 0)
  908.     {
  909.     HEprint(stderr, 0);
  910.     return ret;
  911.     }
  912.     return Hclose(fid);
  913. }
  914.  
  915. #ifdef PROTOTYPE
  916. int getNewRef(char *file, uint16 *pRef)
  917. #else
  918. int getNewRef(file, pRef)
  919.     char *file;
  920.     uint16 *pRef;
  921. #endif
  922. {
  923.     int32 fid;
  924.  
  925.     if ((fid = Hopen(file, DFACC_READ | DFACC_WRITE, 0)) == (uint32)NULL)
  926.     /* a little tricky here */
  927.     if (HEvalue(0) != DFE_FNF || (fid = Hopen(file, DFACC_ALL, 0)) == (uint32)NULL)
  928.     {
  929.         HEprint(stderr, 0);
  930.         return FAIL;
  931.     }
  932.     *pRef = Hnewref(fid);
  933.     return Hclose(fid);
  934. }
  935.  
  936. #ifdef PROTOTYPE
  937. int writeAnnot(char *file, uint16 tag, uint16 ref)
  938. #else
  939. int writeAnnot(file, tag, ref)
  940.     char *file;
  941.     uint16 tag;
  942.     uint16 ref;
  943. #endif
  944. {
  945.     char *data;
  946.     int32 eltLength;
  947.     intn tmp;
  948.     char *p;
  949.     uint16 newRef;
  950.  
  951.     while (tag == 0) {
  952.       printf("Attach to what tag? (> 0)");
  953.       scanf("%d", &tmp);
  954.       tag = (uint16) tmp;
  955.     }
  956.  
  957.     while (ref == 0) {
  958.       printf("Attach to what ref? (> 0)");
  959.       scanf("%d", &tmp);
  960.       ref = (uint16) tmp;
  961.     }
  962.  
  963.     eltLength = getElement(he_currDesc, &data);
  964.     if (eltLength <= 0) {
  965.       fprintf(stderr,"Cannot get element: tag %d ref %d.\n",
  966.               he_desc[he_currDesc].tag, he_desc[he_currDesc].ref);
  967.       return FAIL;
  968.     }
  969.  
  970.     p = data;
  971.  
  972.     /*
  973.      *  This is really ugly...
  974.      */
  975.     UINT16ENCODE(p, tag);
  976.     UINT16ENCODE(p, ref);
  977.  
  978.     if (getNewRef(file, &newRef) < 0) {
  979.       fprintf(stderr,"Error getting new ref number.\n");
  980.       return FAIL;
  981.     }
  982.     
  983.     return putElement(file, he_desc[he_currDesc].tag, newRef, data, eltLength);
  984. }
  985.  
  986. #ifdef PROTOTYPE
  987. int32 getAnn(int ann, int16 tag, int16 ref, char **pBuf)
  988. #else
  989. int32 getAnn(ann, tag, ref, pBuf)
  990.     int ann;
  991.     uint16 tag;
  992.     uint16 ref;
  993.     char **pBuf;
  994. #endif
  995. {
  996.     int32 len;
  997.  
  998.     if (ann == HE_LABEL)
  999.     {
  1000.     len = DFANgetlablen(he_file, tag, ref);
  1001.     if (len > 0)
  1002.     {
  1003.         *pBuf = (char *) malloc(len+1);
  1004.         DFANgetlabel(he_file, tag, ref, *pBuf, len+1);
  1005.     }
  1006.     else
  1007.         *pBuf = NULL;
  1008.     }
  1009.     else
  1010.     {
  1011.     len = DFANgetdesclen(he_file, tag, ref);
  1012.     if (len > 0)
  1013.     {
  1014.         *pBuf = (char *) malloc(len);
  1015.         DFANgetdesc(he_file, tag, ref, *pBuf, len);
  1016.     }
  1017.     else
  1018.         *pBuf = NULL;
  1019.     }
  1020.     return len;
  1021. }
  1022.  
  1023. #ifdef PROTOTYPE
  1024. int putAnn(int ann, uint16 tag, uint16 ref, char *buf, int32 len)
  1025. #else
  1026. int putAnn(ann, tag, ref, buf, len)
  1027.     int ann;
  1028.     uint16 tag;
  1029.     uint16 ref;
  1030.     char *buf;
  1031.     int32 len;
  1032. #endif
  1033. {
  1034.     int ret;
  1035.  
  1036.     if (ann == HE_LABEL)
  1037.     ret = DFANputlabel(he_file, tag, ref, buf);
  1038.     else
  1039.     ret = DFANputdesc(he_file, tag, ref, buf, len);
  1040.     if (ret < 0)
  1041.     HEprint(stderr, 0);
  1042.  
  1043.     return ret;
  1044. }
  1045.  
  1046. #ifdef PROTOTYPE
  1047. int32 readFromFile(char *file, char **pBuf)
  1048. #else
  1049. int32 readFromFile(file, pBuf)
  1050.     char *file;
  1051.     char **pBuf;
  1052. #endif
  1053. {
  1054.     FILE *fp;
  1055.     int32 soFar;
  1056.     int32 bufLen;
  1057.     int32 read;
  1058.  
  1059.     fp = fopen(file, "r");
  1060.     if (fp == NULL) return FAIL;
  1061.  
  1062.     soFar = 0;
  1063.     bufLen = 0;
  1064.     for (read = HE_BUF_SZ; read == HE_BUF_SZ; soFar += read)
  1065.     {
  1066.     bufLen += HE_BUF_SZ;
  1067.     if (bufLen == HE_BUF_SZ)
  1068.         *pBuf = (char *) malloc(bufLen);
  1069.     else
  1070.         *pBuf = (char *) realloc(*pBuf, bufLen);
  1071.     if (*pBuf == NULL) return FAIL;
  1072.  
  1073.     read = fread((*pBuf)+soFar, 1, HE_BUF_SZ, fp);
  1074.     }
  1075.     *pBuf = (char *) realloc(*pBuf, soFar + 1);
  1076.     (*pBuf)[soFar] = '\0';
  1077.     fclose(fp);
  1078.     return soFar;
  1079. }
  1080.  
  1081. /* ---- table for operators -------- */
  1082. struct {
  1083.     char *str;
  1084.     int key;
  1085. } he_optTab[] =
  1086. {
  1087. {"readonly", HE_RDONLY},
  1088. {"all", HE_ALL},
  1089. {"backup", HE_BACKUP},
  1090. {"batch", HE_BATCH},
  1091. {"help", HE_HELP},
  1092. {"longout", HE_LONGOUT},
  1093. {"nobackup", HE_NOBACKUP},
  1094. {"remote", HE_REMOTE},
  1095. {"verbose", HE_VERBOSE},
  1096. {"position", HE_POSITION},
  1097. {"expansion", HE_EXPANSION},
  1098. {"large", HE_LARGE},
  1099. {"offset", HE_OFFSET},
  1100. {"ascii", HE_ASCII},
  1101. {"octal", HE_OCTAL},
  1102. {"hexadecimal", HE_HEX},
  1103. {"decimal", HE_DECIMAL},
  1104. {"float", HE_FLOAT},
  1105. {"dimensions", HE_DIMS},
  1106. {"image", HE_IMAGE},
  1107. {"palette", HE_PALETTE},
  1108. {"raster", HE_RASTER},
  1109. {"rle", HE_RLE},
  1110. {"compress", HE_RLE},
  1111. {"imcomp", HE_IMCOMP},
  1112. {"group", HE_DOGROUP},
  1113. {"file", HE_FILE},
  1114. {"keep", HE_KEEP},
  1115. {"length", HE_LENGTH},
  1116. {"attachto", HE_ATTACHTO},
  1117. {"label", HE_LABEL},
  1118. {"descriptor", HE_DESCRIPTOR},
  1119. {"editor", HE_EDITOR},
  1120. {"byte",   HE_BYTE},
  1121. {"short",  HE_SHORT},
  1122. {"double", HE_DOUBLE},
  1123. {"raw",    HE_RAW},
  1124. {NULL, 0},
  1125. };
  1126.  
  1127. #ifdef PROTOTYPE
  1128. int findOpt(char *word)
  1129. #else
  1130. int findOpt(word)
  1131.     char *word;
  1132. #endif
  1133. {
  1134.     int len;
  1135.     int found = -1;
  1136.     register int i;
  1137.  
  1138.     len = strlen(word);
  1139.  
  1140.     for (i = 0; he_optTab[i].str; i++)
  1141.     if (!strncmp(he_optTab[i].str, word, len))
  1142.     {
  1143.         /* exact match */
  1144.         if (strlen(he_optTab[i].str) == len)
  1145.         return he_optTab[i].key;
  1146.  
  1147.         if (found < 0)
  1148.         found = i;
  1149.         else
  1150.         return HE_AMBIG;
  1151.     }
  1152.  
  1153.     if (found < 0)
  1154.     return HE_NOTFOUND;
  1155.  
  1156.     return he_optTab[found].key;
  1157. }
  1158.  
  1159. #ifdef PROTOTYPE
  1160. char * catStr(char *s, char *s1)
  1161. #else
  1162. char * catStr(s, s1)
  1163.     register char *s, *s1;
  1164. #endif
  1165. {
  1166.     char *t;
  1167.  
  1168.     t = (char *) malloc(strlen(s) + strlen(s1) + 1);
  1169.     strcpy(t, s);
  1170.     strcat(t, s1);
  1171.     return t;
  1172. }
  1173.  
  1174. #ifdef PROTOTYPE
  1175. char *copyStr(char *s)
  1176. #else
  1177. char *copyStr(s)
  1178.     register char *s;
  1179. #endif
  1180. {
  1181.     char *t;
  1182.  
  1183.     t = (char *) malloc(strlen(s) + 1);
  1184.     strcpy(t, s);
  1185.     return t;
  1186. }
  1187.  
  1188. #ifdef PROTOTYPE
  1189. int isGrp(uint16 tag)
  1190. #else
  1191. int isGrp(tag)
  1192.     uint16 tag;
  1193. #endif
  1194. {
  1195.     switch(tag)
  1196.     {
  1197.     case DFTAG_RIG:
  1198.     case DFTAG_SDG:
  1199.     case DFTAG_NDG:
  1200.       /* and other group tags */
  1201.       return 1;
  1202.     default:
  1203.       return 0;
  1204.     }
  1205. }
  1206.  
  1207. #ifdef PROTOTYPE
  1208. int HEquit(HE_CMD *cmd)
  1209. #else
  1210. int HEquit(cmd)
  1211.     HE_CMD *cmd;
  1212. #endif
  1213. {
  1214.     if (cmd->argc > 1)
  1215.     {
  1216.     puts("quit");
  1217.     puts("\tQuits this application.");
  1218.     return HE_OK;
  1219.     }
  1220.     return quit(0);
  1221. }
  1222.  
  1223. #ifdef PROTOTYPE
  1224. int quit(int status)
  1225. #else
  1226. int quit(status)
  1227.     int status;
  1228. #endif
  1229. {
  1230.     if (fileOpen())
  1231.     {
  1232.     if (closeFile(0) < 0)
  1233.         return HE_FAIL;
  1234.     }
  1235.     exit(status);
  1236.     return SUCCEED;
  1237. }
  1238.  
  1239. #ifdef PROTOTYPE
  1240. int HEhelp(HE_CMD *dummy)
  1241. #else
  1242. int HEhelp(dummy)
  1243.      HE_CMD *dummy;
  1244. #endif
  1245. {
  1246.     help();
  1247.     return HE_OK;
  1248. }
  1249.  
  1250. #ifdef PROTOTYPE
  1251. void help(void)
  1252. #else
  1253. void help()
  1254. #endif
  1255. {
  1256.   /* print some help informations */
  1257.   printf("hdfed allows sophisticated HDF users to manipulate the elements in");
  1258.   printf(" an HDF file.\nThese manipulations include selecting groups and ");
  1259.   printf("showing information about\nthem, dumping them to the output, ");
  1260.   printf("writing them to new files, deleting them,\ninserting them, ");
  1261.   printf("replacing, say, the palette of an r8 group, and editing the\n");
  1262.   printf("text labels and descriptions of any element.\n\n");
  1263.  
  1264.   printf("hdfed will NOT allow the user to *arbitrarily* modify binary data ");
  1265.   printf("in the file or\nany element, though it allows modification of tag ");
  1266.   printf("and reference numbers within\nstrict constraints.  The user should");
  1267.   printf(" not attempt to alter individual bytes.  It\nis acceptable,");
  1268.   printf(" however, to replace an element with another of the same type.\n\n");
  1269.  
  1270.   printf("hdfed can be used both interactively or in 'batch' mode.  See the ");
  1271.   printf("\"HDF Calling\nInterfaces and Utilities\" manual section on hdfed ");
  1272.   printf("for an example.\n\n");
  1273.  
  1274.   printf("List of commands:");
  1275.   printf(    "\tannotate   dump    if      open    putr8    unalias\n");
  1276.   printf("\t\t\tclose      getr8   info    prev    revert   wait\n");
  1277.   printf("\t\t\tdelete     help    next    put     select   write\n");
  1278.  
  1279.   printf("\nPredicates for 'if' 'select' 'next' and 'prev' are of the form\n");
  1280.   printf("\ttag = 3 ref = 2 image_size < 1000 label = \"abc\"\n");
  1281.   printf("Type <command> -help for usage of <command>.  DO NOT type the");
  1282.   printf(" command without\narguments and expect help.  Some commands delete");
  1283.   printf(" objects and do not need any\narguments.  If you are learning to ");
  1284.   printf("use hdfed, try it on an expendable file.\n");
  1285.  
  1286. }
  1287.  
  1288. int HEwait(cmd)
  1289.     HE_CMD *cmd;
  1290. {
  1291.     int c;
  1292.  
  1293.     if (cmd->argv[1][0] == '-' && findOpt(cmd->argv[1] + 1) == HE_HELP) {
  1294.       printf("wait [<message>]\n");
  1295.       printf("\tPrints message and then wait for user to hit return\n");
  1296.       return HE_OK;
  1297.     }
  1298.  
  1299.     printf("%s\nPress return to continue.", cmd->argv[1]);
  1300.     do c = getchar();
  1301.     while (c != '\n');
  1302.  
  1303.     return HE_OK;
  1304. }
  1305.  
  1306. #ifdef PROTOTYPE
  1307. void deleteCmd(HE_CMD *cmd)
  1308. #else
  1309. void deleteCmd(cmd)
  1310.     HE_CMD *cmd;
  1311. #endif
  1312. {
  1313.     register int i;
  1314.  
  1315.     if (cmd == NULL) return;
  1316.     if (cmd->next != NULL) deleteCmd(cmd->next);
  1317.     if (cmd->sub != NULL) deleteCmd(cmd->sub);
  1318.     for (i = 0; i < cmd->argc; i++)
  1319.     if (cmd->argv[i] != NULL) free(cmd->argv[i]);
  1320.     free(cmd);
  1321. }
  1322.  
  1323. /* -------------- routines to manipulate templates --------------------- */
  1324.  
  1325. #define TEMPLATE_CHAR1 '#'
  1326. #define TEMPLATE_CHAR2 '@'
  1327. #define TEMPLATE_CHAR3 '%'
  1328.  
  1329. #ifdef PROTOTYPE
  1330. void convertTemplate(char *template, int n1, int n2, int n3, char **pname)
  1331. #else
  1332. void convertTemplate(template, n1, n2, n3, pname)
  1333.     char *template;
  1334.     int n1, n2, n3;
  1335.     char **pname;
  1336. #endif
  1337. {
  1338.     char s1[20], s2[20], s3[20];
  1339.     char *t;
  1340.  
  1341.     sprintf(s1, "%1d", n1);
  1342.     sprintf(s2, "%1d", n2);
  1343.     sprintf(s3, "%1d", n3);
  1344.  
  1345.     *pname = t = (char *) malloc(strlen(template) + 61);
  1346.  
  1347.     while (*template)
  1348.     switch(*template)
  1349.     {
  1350.     case TEMPLATE_CHAR1:
  1351.         fillTemplate(&template, &t, s1, TEMPLATE_CHAR1);
  1352.         break;
  1353.     case TEMPLATE_CHAR2:
  1354.         fillTemplate(&template, &t, s2, TEMPLATE_CHAR2);
  1355.         break;
  1356.     case TEMPLATE_CHAR3:
  1357.         fillTemplate(&template, &t, s3, TEMPLATE_CHAR3);
  1358.         break;
  1359.     default:
  1360.         *t++ = *template++;
  1361.     }
  1362.     *t = '\0';
  1363. }
  1364.  
  1365. #ifdef PROTOTYPE
  1366. void fillTemplate(char **template, char **pout, char *s, char templateChar)
  1367. #else
  1368. void fillTemplate(template, pout, s, templateChar)
  1369.     char **template;
  1370.     char **pout;
  1371.     char *s;
  1372.     char templateChar;
  1373. #endif
  1374. {
  1375.     int templateLen, sLen;
  1376.  
  1377.     /* count length of template to replace */
  1378.     for (templateLen = 0; **template == templateChar;
  1379.      (*template)++, templateLen++);
  1380.     sLen = strlen(s);
  1381.  
  1382.     /* fill with zero's if the space reserved in template is
  1383.        longer than the length of s */
  1384.     for (; templateLen > sLen; templateLen--)
  1385.     *(*pout)++ = '0';
  1386.  
  1387.     while (*s) *(*pout)++ = *s++;
  1388. }
  1389.  
  1390. /* end of he-main.c */
  1391.